/* Copyright 2014 Pasi J. Elo, blackdogspark@hotmail.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

	   http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 
   This class is still in early stage and might not work as expected.
 */

using GHI.Glide;
using GHI.Glide.Display;
using GHI.Glide.Geom;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation.Media;
using PJE.GlideEx.Properties;

namespace PJE.GlideEx.UI
{
	public sealed class ScrollBar : DisplayObject
	{
		private Rectangle _rectangleTouchUp;
		private Rectangle _rectangleTouchDown;
		private Rectangle _rectangleThumb;
		private int _maximum;
		private double _viewableRatio;
		private double _scrollBarArea;
		private int _thumbLength;
		private int _thumbY;
		private double _value;
		private bool _isTouched;
		private bool _arrowUpIsTouched;
		private bool _arrowDownIsTouched;

		public Bitmap ButtonUp;
		public Bitmap ButtonDown;
		public Bitmap MiddleUp;
		public int SmallChange = 1;

		public int LargeChange = 10;
		/// <summary>
		/// Color to tint the button.
		/// </summary>
		public Color TintColor = Colors.Black;

		/// <summary>
		/// Amount of tint to apply.
		/// </summary>
		public ushort TintAmount = 0;

		public Color TrackColor = Colors.LightGray;

		public int ArrowHeight = 32;

		public event ValueChangedEventHandler ValueChangedEventHandler;

		public int Maximum
		{
			get
			{
				return _maximum;
			}
			set
			{
				_maximum = value;
				double height = Height;
				double max = _maximum;
				_viewableRatio = height / max;
				_scrollBarArea = Height - ArrowHeight * 2;
				_thumbLength = (int)(_scrollBarArea * _viewableRatio);
			}
		}

		public double Value
		{
			get
			{
				return _value;
			}
			set
			{
				_value = value;
				if (_value > _maximum)
					_value = _maximum;
				else if (_value < 0)
					_value = 0;
				ThumbPosition();
				if (ValueChangedEventHandler != null)
					ValueChangedEventHandler(new ValueChangedEventArgs(_value));
			}
		}

		/// <summary>
		/// Disposes all disposable objects in this object.
		/// </summary>
		public override void Dispose()
		{
			ButtonUp.Dispose();
			ButtonDown.Dispose();
		}

		public ScrollBar(string name, ushort alpha, int x, int y, int width, int height)
		{
			//Defaults
			X = x;
			Y = y;
			Width = width;
			Height = height;
			Alpha = alpha;
			Name = name;

			ButtonUp = new Bitmap(Resources.GetBytes(Resources.BinaryResources.Button_Up), Bitmap.BitmapImageType.Gif);
			ButtonDown = new Bitmap(Resources.GetBytes(Resources.BinaryResources.Button_Down), Bitmap.BitmapImageType.Gif);
			MiddleUp = new Bitmap(Resources.GetBytes(Resources.BinaryResources.Middle_Up), Bitmap.BitmapImageType.Gif);

			_rectangleThumb.Height = Height - (ArrowHeight * 2);
			_rectangleThumb.Width = Width;

			_rectangleThumb.X = X;
			_rectangleThumb.Y = ArrowHeight;

			_rectangleTouchDown.Width = Width;
			_rectangleTouchDown.Height = ArrowHeight;

			_rectangleTouchUp.Width = Width;
			_rectangleTouchUp.Height = ArrowHeight;

			_rectangleTouchDown.X = X;
			_rectangleTouchDown.Y = Height - ArrowHeight;

			_rectangleTouchUp.X = X;
			_rectangleTouchUp.Y = Y;
		}

		public override void Render()
		{
			var y = Y + Parent.Y;
			var x = X + Parent.X;

			var alpha = (Enabled) ? Alpha : (ushort)(Alpha / 2);

			if (TintAmount > 0)
			{
				Parent.Graphics.DrawLine(TintColor, 1, x + 2, y, (x + Width) - 3, y);
				Parent.Graphics.DrawLine(TintColor, 1, x + 1, y + 1, (x + Width) - 2, y + 1);
				Parent.Graphics.DrawRectangle(0, 0, x, y + 2, Width, Height - 4, 0, 0, TintColor, 0, 0, 0, 0, 0, alpha);
				Parent.Graphics.DrawLine(TintColor, 1, x + 1, (y + Height) - 2, (x + Width) - 2, (y + Height) - 2);
				Parent.Graphics.DrawLine(TintColor, 1, x + 2, (y + Height) - 1, (x + Width) - 3, (y + Height) - 1);

				alpha -= TintAmount;
				/*
				if (alpha < 0)
					alpha = 0;
				 */
			}

			Parent.Graphics.DrawRectangle(TrackColor, 0, x, y, Width, Height, 0, 0, TrackColor, 0, 0,
				TrackColor, 0, 0, alpha);

			Parent.Graphics.Scale9Image(x, y + ArrowHeight + _thumbY, Width, _thumbLength, MiddleUp, 5, alpha);

			if (_arrowUpIsTouched)
				Parent.Graphics.Scale9Image(x, y, Width, ArrowHeight, ButtonDown, 5, alpha);
			else if (!_arrowUpIsTouched)
				Parent.Graphics.Scale9Image(x, y, Width, ArrowHeight, ButtonUp, 5, alpha);

			if (_arrowDownIsTouched)
				Parent.Graphics.Scale9Image(x, Height - ArrowHeight, Width, ArrowHeight, ButtonDown, 5, alpha);
			else if (!_arrowDownIsTouched)
				Parent.Graphics.Scale9Image(x, Height - ArrowHeight, Width, ArrowHeight, ButtonUp, 5, alpha);

			base.Render();
		}

		public double GetThumbCenter()
		{
			return _thumbY + (_thumbLength / 2) + ArrowHeight;
		}

		public int ThumbPosition()
		{
			var perc = _value / _maximum;
			var height = _scrollBarArea - _thumbLength;
			var y = height * perc;

			_thumbY = (int)y;

			return _thumbY;
		}

		public override TouchEventArgs OnTouchDown(TouchEventArgs e)
		{
			var p = e.Point;
			if (_isTouched) return base.OnTouchDown(e);

			if (_rectangleTouchUp.Contains(p))
			{
				_arrowUpIsTouched = _isTouched = true;
				Value -= SmallChange;
				Invalidate();
			}
			else if (_rectangleTouchDown.Contains(p))
			{
				_arrowDownIsTouched = _isTouched = true;
				Value += SmallChange;
				Invalidate();

			}
			else if (_rectangleThumb.Contains(p))
			{
				_isTouched = true;
				if (p.Y > GetThumbCenter())
					Value += LargeChange;
				else if (p.Y < GetThumbCenter())
					Value -= LargeChange;
				Invalidate();
			}

			return base.OnTouchDown(e);
		}

		public override TouchEventArgs OnTouchUp(TouchEventArgs e)
		{
			_arrowUpIsTouched = _arrowDownIsTouched = _isTouched = false;
			Invalidate();
			return base.OnTouchUp(e);
		}
	}
	public delegate void ValueChangedEventHandler(ValueChangedEventArgs e);

	public class ValueChangedEventArgs : EventArgs
	{
		public double Value { get; set; }

		public ValueChangedEventArgs(double value)
		{
			Value = value;
		}
	}
}
